﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using AForge.Video.DirectShow;
using INIFILE;


namespace CameraCapture
{
    public partial class Form1 : Form
    {
        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        [System.Runtime.InteropServices.ComVisibleAttribute(true)]
        [System.Security.SecuritySafeCritical]
        [DllImport("User32.DLL")]
        public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
        [DllImport("User32.DLL")]
        public static extern bool ReleaseCapture();
        [DllImport("USER32.DLL")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);
        public const uint WM_SYSCOMMAND = 0x0112;
        public const int SC_MOVE = 61456;
        public const int HTCAPTION = 2;

        private FilterInfoCollection videoDevices;
        private VideoCaptureDevice videoSource;

        SerialPort sp1 = new SerialPort();
        SerialPortDataController serialPortDataController;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                INIFILE.Profile.LoadProfile();//加载所有


                
                tbFolder.Text = Profile.G_Folder;
                contextMenuStrip1.Renderer = new MenuRender.AioMenuRender();

                initComboboxCameras();
            }
            catch (ApplicationException)
            {

            }
            try
            {
                serialPortDataController = new SerialPortDataController(sp1);
                serialPortDataController.CameraDelayEvent += spd_CameraDelayEvent;
                serialPortDataController.StateEvent += serialPortDataController_StateEvent;
                serialPortDataController.CameraConenctEvent += serialPortDataController_CameraConenctEvent;
                serialPortDataController.RecvDataEvent += serialPortDataController_RecvDataEvent;
                serialPortDataController.SendDataEvent += serialPortDataController_SendDataEvent;
                serialPortDataController.lightDataEvent += serialPortDataController_lightDataEvent;
                
                RefreshCOM();

                serialPortDataController.bStop = cbContinue.Checked;

                if (!sp1.IsOpen)
                {
                    sp1.Open();
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message + "端口被占用");
            }
        }

        /// <summary>
        /// 刷新串口
        /// </summary>
        private void RefreshCOM()
        {
            int index = 0;
            cbCOM.Items.Clear();
            foreach (string portname in System.IO.Ports.SerialPort.GetPortNames())
            {   //获取串口
                comboBoxAddItem(cbCOM, portname);
                if (portname.Equals(Profile.G_PORTNAME))
                {
                    cbCOM.SelectedIndex = index;
                }
                index++;
            }
        }


        private void serialPortDataController_lightDataEvent(State state)
        {
            this.BeginInvoke((Action)(() =>
            {
                ErrorLabel.Text = ErrorStrAttribute.GetStr(state);
            }));
        }

        private void serialPortDataController_SendDataEvent(byte[] sendData)
        {
            tbAppendText(tb_send, sendData,sendtextcount);
        }

        private byte[] HexStringToByteArray(string s)
        {
            s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
                buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            return buffer;
        }

        int recvtextcount = 0;
        int sendtextcount = 0;

        private void serialPortDataController_RecvDataEvent(byte[] recvData)
        {
            tbAppendText(tb_recv,recvData,recvtextcount);

        }

        private void tbAppendText(TextBox textBox, byte[] bytesData,int textcount)
        {
            textcount++;
            this.BeginInvoke((Action)(() =>
            {
                foreach (byte bt in bytesData)
                {
                    string hexstr = Convert.ToString((int)bt, 16).PadLeft(2, '0');
                    textBox.AppendText(hexstr);
                }
                textBox.AppendText("  ");
                if (textcount % 3 == 0)
                {
                    textBox.Text += "\r\n";
                    textBox.ScrollToCaret();
                    this.tb_recv.Select(textBox.TextLength, 0);
                }
            }));
        }
        private void serialPortDataController_CameraConenctEvent()
        {
            this.BeginInvoke((Action)(() =>
            {
                CameraConn();
                ErrorLabel.Text = "";
            }));
        }

        private void serialPortDataController_StateEvent(State state)
        {
            switch (state)
            {

                case State.Sleep:
                    //this.BeginInvoke((Action)(() =>
                    //{
                    //    StopVideoPlayer();
                    //}));
                    break;
                case State.Timeout:
                    serialPortDataController.Send(Instruction.stop_instruction);

                    break;
                case State.Lock1:
                    serialPortDataController.Send(Instruction.stop_instruction);
                    break;
                case State.Lock2:
                    serialPortDataController.Send(Instruction.stop_instruction);
                    break;
                case State.Unknown:
                    break;
                default:
                    
                    break;
            }

            this.BeginInvoke((Action)(() =>
            {
                ErrorLabel.Text = ErrorStrAttribute.GetStr(state);
            }));

        }

        private void spd_CameraDelayEvent(int obj)
        {
            delayCapture(obj);
        }

        private void initComboboxCameras()
        {   
            // 枚举所有视频输入设备
            cmbCameras.Items.Clear();
            videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            if (videoDevices.Count == 0)
            {
                comboBoxAddItem(cmbCameras, "No capture devices");
                videoDevices = null;
            }

            if (videoDevices != null)
            {
                for (int index = 0; index < videoDevices.Count; index++)
                {
                    comboBoxAddItem(cmbCameras, videoDevices[index].Name);
                    if (videoDevices[index].Name.Equals(Profile.G_CAMERA))
                    {
                        cmbCameras.SelectedIndex = index;
                    }
                }
                if (cmbCameras.SelectedIndex == -1)
                {
                    cmbCameras.SelectedIndex = 0;
                }
            }

        }

        private void comboBoxAddItem(DSkin.Controls.DSkinComboBox combobox, string text)
        {
            var label = new DSkin.DirectUI.DuiLabel();
            label.Text = text;
            label.Width = cmbCameras.Width;
            label.Height = cmbCameras.Height;
            label.TextAlign = ContentAlignment.MiddleLeft;
            Font font = new Font(cmbCameras.Font.FontFamily, cmbCameras.Font.Size, cmbCameras.Font.Style);
            label.Font = font;
            combobox.Items.Add(label);
        }
        #region 视频截图
        //启动设备
        private void CameraConn()
        {
            if (!videPlayer.IsRunning && videoDevices!=null)
            {
                
                //videoSource.DesiredFrameSize = new Size(3264, 2448);//新版本提示已过时
                //videoSource.DesiredFrameRate = 1;

                videPlayer.Start();
            }
        }

        //启动
        private void btStart_Click(object sender, EventArgs e)
        {
            CameraConn();
        }

        //拍照
        private void btImage_Click(object sender, EventArgs e)
        {
            CaptureImg();
        }

        private bool CaptureImg()
        {
            try
            {
                bool capturesucceed=false;
                string filePath = tbFolder.Text+"\\";
                if (!Directory.Exists(filePath))
                {
                    Directory.CreateDirectory(filePath);
                }
                Bitmap bitmap = videPlayer.GetCurrentVideoFrame();

                if (bitmap != null)
                {
                    string fileName = string.Format("{0:yyyyMMddHHmmssfff}", DateTime.Now) + ".jpg";
                    bitmap.Save(filePath + fileName, ImageFormat.Jpeg);
                    bitmap.Dispose();
                    capturesucceed = true;
                }
                return capturesucceed;
            }
            catch (Exception ex)
            {
                ErrorLabel.Text = ex.Message;
                return false;
            }
        }




        //断开
        private void btStop_Click(object sender, EventArgs e)
        {
            StopVideoPlayer();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            StopVideoPlayer();
            sp1.Close();
        }

        private void StopVideoPlayer()
        {
            videPlayer.SignalToStop();
            videPlayer.WaitForStop();
        }
        #endregion

        private void delayCapture(int cameradelay)
        {
            Thread captureThread = new Thread(new ThreadStart(() =>
            {
                serialPortDataController.Send(Instruction.stop_instruction);
                System.Threading.Thread.Sleep(cameradelay);
                serialPortDataController.Send(Instruction.down_instruction);
                System.Threading.Thread.Sleep(cameradelay);

                this.BeginInvoke((Action)(() =>
                {
                    if (CaptureImg())
                    {
                        serialPortDataController.Send(Instruction.stop_instruction);
                        System.Threading.Thread.Sleep(SerialPortDataController.cameradelay);

                        if (!cbContinue.Checked)
                        {
                            serialPortDataController.Send(Instruction.startscroll_instruction);
                        }
                    }
                    else
                    {
                        ErrorLabel.Text = "拍照失败";
                    }
                }));

            }));
            captureThread.IsBackground = true;
            captureThread.Start();
        }


        private void btClose_Click(object sender, EventArgs e)
        {
            Exit();
        }

        private void Exit()
        {
            if (cmbCameras.SelectedDuiControl != null)
            {
                Profile.G_CAMERA = cmbCameras.SelectedDuiControl.Text;
            }

            try
            {
                this.Visible = false;

                Profile.G_Folder = tbFolder.Text;
                Profile.SaveProfile();
                StopVideoPlayer();
                if (serialPortDataController != null)
                {
                    serialPortDataController.Send(Instruction.stop_instruction);
                }
                sp1.Close();
                this.notifyIcon1.Dispose();
                System.Threading.Thread.Sleep(1000);
                while (videPlayer.IsRunning)
                {
                    System.Threading.Thread.Sleep(1000);
                }
                Application.Exit();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                System.Environment.Exit(0);
            }
        }

        private void btminimise_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
        }

        private void Form1_SizeChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                    this.Hide(); //隐藏窗体
                    notifyIcon1.Visible = true; //使托盘图标可见
            }
            else
                notifyIcon1.Visible = true;
        }



        private void notifyIcon1_MouseClick(object sender, EventArgs e)
        {
            MouseEventArgs mouse_e = (MouseEventArgs)e;
            if (mouse_e.Button == MouseButtons.Left)
            {
                setWindowState(FormWindowState.Normal);
            }
        }

        public void setWindowState(FormWindowState windowstate)
        {
            this.Visible = true;
            this.WindowState = windowstate;
            this.Activate();
            //this.BringToFront();
        }

        private void NormalToolStripMenuItem_Click(object sender, EventArgs e)
        {
            setWindowState(FormWindowState.Normal);
        }

        private void ExitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Exit();
        }


        //处理无边框窗体的拖动
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == 0x84)
            {
                switch (m.Result.ToInt32())
                {
                    case 1:
                        m.Result = new IntPtr(2);
                        break;
                }
            }
            else if (m.Msg == 0x112)
            {
                switch ((int)m.WParam)
                {
                    //禁止双击标题栏
                    case 0xf122:
                        m.WParam = IntPtr.Zero;
                        break;
                }
            }
            base.WndProc(ref m);

        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            ReleaseCapture();
            SendMessage(Handle, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);
        }

        private void btSelectFolder_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                tbFolder.Text = folderBrowserDialog1.SelectedPath;
            }
        }

        private void cmbCameras_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (videoDevices != null)
            {
                int a = cmbCameras.SelectedIndex;
                videoSource = new VideoCaptureDevice(videoDevices[cmbCameras.SelectedIndex].MonikerString);
                foreach (VideoCapabilities videocapabilities in videoSource.VideoCapabilities)
                {
                    comboBoxAddItem(combobox_resolution, videocapabilities.FrameSize.Width + "*" + videocapabilities.FrameSize.Height);
                }
                int resolutionindex = Convert.ToInt32(Profile.G_ResolutionIndex);
                if (resolutionindex < combobox_resolution.Items.Count)
                {
                    combobox_resolution.SelectedIndex = resolutionindex;
                }
            }

            
            //videoSource.VideoCapabilities
        }

        private void combobox_resolution_SelectedIndexChanged(object sender, EventArgs e)
        {
            videoSource.VideoResolution = videoSource.VideoCapabilities[combobox_resolution.SelectedIndex];
            videPlayer.VideoSource = videoSource;
            if (videPlayer.IsRunning)
            {
                StopVideoPlayer();
            }
            if (!videPlayer.IsRunning && videoDevices != null)
            {
                videPlayer.Start();
            }
            Profile.G_ResolutionIndex = combobox_resolution.SelectedIndex.ToString();
        }

        #region 调试区域
        private void bt_Magnet_Click(object sender, EventArgs e)
        {
            //压下电磁铁
            serialPortDataController.Send(Instruction.down_instruction);
        }

        private void btMathine_Click(object sender, EventArgs e)
        {
            //转动电机
            serialPortDataController.Send(Instruction.startscroll_instruction);
        }

        private void btStopMagnetMathine_Click(object sender, EventArgs e)
        {
            //抬起电磁铁停止电机
            serialPortDataController.Send(Instruction.stop_instruction);
        }
        #endregion


        private void cb_test_CheckedChanged(object sender, EventArgs e)
        {
                dSkinTestPanel.Visible = cb_test.Checked;
        }

        private void btClearRecv_Click(object sender, EventArgs e)
        {
            recvtextcount = 0;
            tb_recv.Text = "";
        }

        private void btClearSend_Click(object sender, EventArgs e)
        {
            sendtextcount = 0;
            tb_send.Text = "";
        }

        private void comboboxComSelectedChanged(object sender, EventArgs e)
        {
            sp1.Close();
            Profile.G_PORTNAME=cbCOM.SelectedDuiControl.Text;
            serialPortDataController.initPort(sp1);
            try
            {
                if (!sp1.IsOpen)
                {
                    sp1.Open();
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message + "端口被占用");
            }
        }

        private void cbCOM_Click(object sender, EventArgs e)
        {
            Console.Write("refreshcom");
            RefreshCOM();
        }

        private void cmbCameras_Click(object sender, EventArgs e)
        {
            
            initComboboxCameras();
        }

        private void cbContinue_CheckedChanged(object sender, EventArgs e)
        {
            serialPortDataController.bStop = cbContinue.Checked;
        }

    }
}
